package org.dromara.common.excel.handler

import cn.hutool.core.collection.CollUtil
import cn.idev.excel.annotation.ExcelProperty
import cn.idev.excel.metadata.data.DataFormatData
import cn.idev.excel.util.StyleUtil
import cn.idev.excel.write.handler.CellWriteHandler
import cn.idev.excel.write.handler.SheetWriteHandler
import cn.idev.excel.write.handler.context.CellWriteHandlerContext
import cn.idev.excel.write.metadata.style.WriteFont
import org.apache.poi.xssf.usermodel.XSSFClientAnchor
import org.apache.poi.xssf.usermodel.XSSFRichTextString
import org.dromara.common.excel.annotation.ExcelNotation
import org.dromara.common.excel.annotation.ExcelRequired

/**
 * 批注、必填
 *
 * @author LikeYouDo
 */
open class DataWriteHandler(
    private val clazz: Class<*>
) : SheetWriteHandler, CellWriteHandler {

    /**
     * 批注
     */
    private var notationMap: MutableMap<String, String> = getNotationMap(clazz)

    /**
     * 头列字体颜色
     */
    private var headColumnMap: MutableMap<String, Short> = getRequiredMap(clazz)

    override fun afterCellDispose(context: CellWriteHandlerContext) {
        if (CollUtil.isEmpty(notationMap) && CollUtil.isEmpty(headColumnMap)) {
            return
        }
        // 第一行
        val cellData = context.firstCellData
        // 第一个格子
        val writeCellStyle = cellData.getOrCreateStyle()

        if (context.head) {
            val dataFormatData = DataFormatData()
            // 单元格设置为文本格式
            dataFormatData.index = 49.toShort()
            writeCellStyle.dataFormatData = dataFormatData
            val cell = context.cell
            val writeSheetHolder = context.writeSheetHolder
            val sheet = writeSheetHolder.sheet
            val workbook = writeSheetHolder.sheet.workbook
            val drawing = sheet.createDrawingPatriarch()
            // 设置标题字体样式
            val headWriteFont = WriteFont()
            // 加粗
            headWriteFont.bold = true
            if (CollUtil.isNotEmpty(headColumnMap) && headColumnMap.containsKey(cell.getStringCellValue())) {
                // 设置字体颜色
                headWriteFont.color = headColumnMap[cell.stringCellValue]
            }
            writeCellStyle.writeFont = headWriteFont
            val cellStyle = StyleUtil.buildCellStyle(workbook, null, writeCellStyle)
            cell.cellStyle = cellStyle

            if (CollUtil.isNotEmpty(notationMap) && notationMap.containsKey(cell.stringCellValue)) {
                // 批注内容
                val notationContext = notationMap[cell.stringCellValue]
                // 创建绘图对象
                val comment = drawing.createCellComment(
                    XSSFClientAnchor(
                        0,
                        0,
                        0,
                        0,
                        cell.columnIndex.toShort().toInt(),
                        0,
                        5.toShort().toInt(),
                        5
                    )
                )
                comment.string = XSSFRichTextString(notationContext)
                cell.cellComment = comment
            }
        }
    }

    companion object {
        /**
         * 获取必填列
         */
        @JvmStatic
        private fun getRequiredMap(clazz: Class<*>): MutableMap<String, Short> {
            val requiredMap: MutableMap<String, Short> = HashMap()
            val fields = clazz.getDeclaredFields()
            for (field in fields) {
                if (!field.isAnnotationPresent(ExcelRequired::class.java)) {
                    continue
                }
                val excelRequired = field.getAnnotation(ExcelRequired::class.java)
                val excelProperty = field.getAnnotation(ExcelProperty::class.java)
                requiredMap[excelProperty.value[0]] = excelRequired.fontColor.getIndex()
            }
            return requiredMap
        }

        /**
         * 获取批注
         */
        @JvmStatic
        private fun getNotationMap(clazz: Class<*>): MutableMap<String, String> {
            val notationMap: MutableMap<String, String> = HashMap()
            val fields = clazz.getDeclaredFields()
            for (field in fields) {
                if (!field.isAnnotationPresent(ExcelNotation::class.java)) {
                    continue
                }
                val excelNotation = field.getAnnotation(ExcelNotation::class.java)
                val excelProperty = field.getAnnotation(ExcelProperty::class.java)
                notationMap[excelProperty.value[0]] = excelNotation.value
            }
            return notationMap
        }
    }
}
